from re import template
from typing import List
import numpy as np
class loadBase:
    """载荷基类"""
    # 是否是作用于单元载荷
    isElementLoad=True
    # LoadType="this is loadType's detail name"
    def __init__(self, name:str):
        self.name=name
    @property
    def get_NodesList(self)->List[int]:
        """返回载荷作用节点的标签列表"""
        return []
    @property
    def get_ElemsList(self)->List[int]:
        return []
    def __str__(self)->str:
        return f"{self.__class__.__name__}:{self.name}"

class ConcentratedLoad(loadBase):
    """节点集中力加载"""
    isElementLoad=False
    def __init__(self, name:str,
                nodeLabels:List[int] ,
                dofth:int,
                value:float):
        """初始化节点集中力载荷对象,nodeLabels为节点标签列表,dofth为节点第几个自由度,value为载荷值,DofNumPerNode为节点自由度数目,globalDofNum为全局自由度数目"""
        super().__init__(name)
        self.nodeLabelList=nodeLabels
        self.dofth=dofth
        self.LoadValue=value
    @property
    def get_NodesList(self):
        return self.nodeLabelList
    def __str__(self)->str:
        return  f"ConcentratedLoad:{self.name}"+\
                f"ConcentratedLoad nodeLabelList:{self.nodeLabelList}"+\
                f"ConcentratedLoad dofth:{self.dofth}"+\
                f"ConcentratedLoad LoadValue:{self.LoadValue}"
class ThermalLoad(loadBase):
    """温度载荷,热膨胀"""
    def __init__(self, name: str,
                ElementLabels:List[int],
                temperature:float=0.0):
        super().__init__(name)
        self.ElementLabels=ElementLabels
        self.Temperature=temperature
    @property
    def get_ElemsList(self)->List[int]:
        return self.ElementLabels
class BodyLoad(loadBase):
    """体力载荷"""
    def __init__(self, name:str,
                ElementLabels:List[int],
                Direction:str, # x,y,z
                value:float):
        super().__init__(name)
        self.ElementLabels=ElementLabels
        self.Direction=Direction
        self.LoadValue=value
    @property
    def get_ElemsList(self)->List[int]:
        return self.ElementLabels
    def __str__(self)->str:
        return f"BodyLoad:{self.name}"+\
        f"BodyLoad ElementLabels:{self.ElementLabels}"+\
        f"BodyLoad Direction:{self.Direction}"+\
        f"BodyLoad LoadValue:{self.LoadValue}"

class PressureLoad(loadBase):
    """压力分布载荷,以外法向为正方向"""
    def __init__(self, name:str,
                ElementLabels:List[int],
                faceIds:List[int],
                value:float):
        """取正值说明单元受拉;定义载荷的作用在的单元面的信息:在??单元的第??面上作用,压力值value"""
        super().__init__(name)
        if len(ElementLabels)!=len(faceIds):
            raise ValueError("数组大小错误")
        self.ElementLabels=ElementLabels
        self.FaceIdList=faceIds
        self.PressureValue=value
    @property
    def get_ElemsList(self)->List[int]:
        return self.ElementLabels    
    def __str__(self):
        return f"PressureLoad: {self.name}\n"+\
                f"Presure Value: {self.PressureValue}"

class SurfaceLoad(loadBase):
    """表面力加载"""
    def __init__(self, name:str,
                ElementLabels:List[int],
                faceIds:List[int],
                directionVector:np.ndarray,
                value:float):
        """定义载荷的作用在的单元面的信息:在??单元的第??面上作用,方向向量directionVector(3,)numpy数组,载荷值value"""
        super().__init__(name)
        if len(ElementLabels)!=len(faceIds):
            raise ValueError("数组大小错误")
        if np.abs(np.linalg.norm(directionVector)-1)>0.0005:
            raise ValueError("方向向量需要是单位向量")
        self.ElementLabels=ElementLabels
        self.FaceIdList=faceIds
        self.DirectionVector=np.array(directionVector)    
        self.LoadValue=value
    @property
    def get_ElemsList(self)->List[int]:
        return self.ElementLabels
    def __str__(self)->str:
        return f"SurfaceLoad:{self.name}"+\
                f"SurfaceLoad ElementLabels:{self.ElementLabels}"+\
                f"SurfaceLoad FaceIdList:{self.FaceIdList}"+\
                f"SurfaceLoad DirectionVector:{self.DirectionVector}"+\
                f"SurfaceLoad LoadValue:{self.LoadValue}"

class DloadOnTruss(loadBase):
    """作用在杆单元上的均布载荷P(N/m),正值表示与杆方向(1 node->2 node)相同,负值表示与杆方向(1 node->2 node)相反"""
    def __init__(self, name:str,
                ElementLabels:List[int],
                value:float):
        """定义载荷的作用在的单元的标签列表ElementLabels,载荷值value"""
        super().__init__(name)
        self.ElementLabels=ElementLabels
        self.LoadValue=value
    @property
    def get_ElemsList(self)->List[int]:
        return self.ElementLabels
    def __str__(self)->str:
        return f"DloadOnTruss:{self.name}"+\
                f"DloadOnTruss ElementLabels:{self.ElementLabels}"+\
                f"DloadOnTruss LoadValue:{self.LoadValue}"

class DloadOnBeam(loadBase):
    """作用在梁单元上的均布载荷P(N/m),正值表示与梁垂直y方向相同,负值表示与梁垂直方向相反"""
    def __init__(self, name:str,
                ElementLabels:List[int],
                value:float):
        """定义载荷的作用在的单元的标签列表ElementLabels,载荷值value"""
        super().__init__(name)
        self.ElementLabels=ElementLabels
        self.LoadValue=value
    @property
    def get_ElemsList(self)->List[int]:
        return self.ElementLabels
    def __str__(self)->str:
        return f"DloadOnBeam:{self.name}"+\
                f"DloadOnBeam ElementLabels:{self.ElementLabels}"+\
                f"DloadOnBeam LoadValue:{self.LoadValue}"

class BcBase:
    """边界条件基类"""
    def __init__(self, name:str):
        self.name=name
    @property
    def get_NodesList(self)->List[int]:
        """返回边界条件作用节点的标签列表"""
        raise NotImplemented("get_NodesList method not implemented") # type: ignore
    
class DisplacementBc(BcBase):
    """强制位移边界条件"""
    def __init__(self, name:str,
                nodeLabels:List[int],
                dofth:int,
                value:float):
        """在节点nodeLabels的第dofth自由度上施加强制位移边界条件,value为边界条件值"""
        super().__init__(name)
        self.NodeLabelList=nodeLabels
        self.Dofth=dofth
        self.Value=value
    @property
    def get_NodesList(self)->List[int]:
        return self.NodeLabelList
